﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework;

namespace GameUtils.Input
{
    public static class PollingInput
    {
        #region Properties
        public static KeyboardState PrevKeyboardState { get; private set; }
        public static KeyboardState CurrKeyboardState { get; private set; }
        public static MouseState PrevMouseState { get; private set; }
        public static MouseState CurrMouseState { get; private set; }

        public static int X
        {
            get { return CurrMouseState.X; }
        }

        public static int Y
        {
            get { return CurrMouseState.Y; }
        }

        public static int Wheel
        {
            get { return CurrMouseState.ScrollWheelValue; }
        }
        #endregion

        #region Constructors
        static PollingInput()
        {
            PreHandleInput();
            PostHandleInput();
        }
        #endregion

        #region Methods
        public static void PreHandleInput()
        {
            CurrKeyboardState = Keyboard.GetState();
            CurrMouseState = Mouse.GetState();
        }

        public static void PostHandleInput()
        {
            PrevKeyboardState = CurrKeyboardState;
            PrevMouseState = CurrMouseState;
        }

        #region Keyboard
        public static bool IsPressed(Keys pKey)
        {
            return CurrKeyboardState.IsKeyDown(pKey);
        }

        public static bool IsReleased(Keys pKey)
        {
            return CurrKeyboardState.IsKeyUp(pKey);
        }

        public static bool IsJustPressed(Keys pKey)
        {
            return CurrKeyboardState.IsKeyDown(pKey) && !PrevKeyboardState.IsKeyDown(pKey);
        }

        public static bool IsJustReleased(Keys pKey)
        {
            return CurrKeyboardState.IsKeyUp(pKey) && !PrevKeyboardState.IsKeyUp(pKey);
        }
        #endregion

        #region Mouse
        public static void SetMousePosition(int pX, int pY)
        {
            Mouse.SetPosition(pX, pY);
        }

        public static bool IsPressed(MouseButton pMouseButton)
        {
            switch (pMouseButton)
            {
                case MouseButton.Left:
                    return CurrMouseState.LeftButton == ButtonState.Pressed;

                case MouseButton.Middle:
                    return CurrMouseState.MiddleButton == ButtonState.Pressed;

                case MouseButton.Right:
                    return CurrMouseState.RightButton == ButtonState.Pressed;

                case MouseButton.X1:
                    return CurrMouseState.XButton1 == ButtonState.Pressed;

                case MouseButton.X2:
                    return CurrMouseState.XButton2 == ButtonState.Pressed;

                default:
                    {
                        string errorMessage = string.Format("Mouse button not supported: '{0}'.", pMouseButton);
                        throw new NotSupportedException(errorMessage);
                    }
            }
        }

        public static bool IsReleased(MouseButton pMouseButton)
        {
            switch (pMouseButton)
            {
                case MouseButton.Left:
                    return CurrMouseState.LeftButton == ButtonState.Released;

                case MouseButton.Middle:
                    return CurrMouseState.MiddleButton == ButtonState.Released;

                case MouseButton.Right:
                    return CurrMouseState.RightButton == ButtonState.Released;

                case MouseButton.X1:
                    return CurrMouseState.XButton1 == ButtonState.Released;

                case MouseButton.X2:
                    return CurrMouseState.XButton2 == ButtonState.Released;

                default:
                    {
                        string errorMessage = string.Format("Mouse button not supported: '{0}'.", pMouseButton);
                        throw new NotSupportedException(errorMessage);
                    }
            }
        }

        public static bool IsJustPressed(MouseButton pMouseButton)
        {
            switch (pMouseButton)
            {
                case MouseButton.Left:
                    return CurrMouseState.LeftButton == ButtonState.Pressed && PrevMouseState.LeftButton != ButtonState.Pressed;

                case MouseButton.Middle:
                    return CurrMouseState.MiddleButton == ButtonState.Pressed && PrevMouseState.MiddleButton != ButtonState.Pressed;

                case MouseButton.Right:
                    return CurrMouseState.RightButton == ButtonState.Pressed && PrevMouseState.RightButton != ButtonState.Pressed;

                case MouseButton.X1:
                    return CurrMouseState.XButton1 == ButtonState.Pressed && PrevMouseState.XButton1 != ButtonState.Pressed;

                case MouseButton.X2:
                    return CurrMouseState.XButton2 == ButtonState.Pressed && PrevMouseState.XButton2 != ButtonState.Pressed;

                default:
                    {
                        string errorMessage = string.Format("Mouse button not supported: '{0}'.", pMouseButton);
                        throw new NotSupportedException(errorMessage);
                    }
            }
        }

        public static bool IsJustReleased(MouseButton pMouseButton)
        {
            switch (pMouseButton)
            {
                case MouseButton.Left:
                    return CurrMouseState.LeftButton == ButtonState.Released && PrevMouseState.LeftButton != ButtonState.Released;

                case MouseButton.Middle:
                    return CurrMouseState.MiddleButton == ButtonState.Released && PrevMouseState.MiddleButton != ButtonState.Released;

                case MouseButton.Right:
                    return CurrMouseState.RightButton == ButtonState.Released && PrevMouseState.RightButton != ButtonState.Released;

                case MouseButton.X1:
                    return CurrMouseState.XButton1 == ButtonState.Released && PrevMouseState.XButton1 != ButtonState.Released;

                case MouseButton.X2:
                    return CurrMouseState.XButton2 == ButtonState.Released && PrevMouseState.XButton2 != ButtonState.Released;

                default:
                    {
                        string errorMessage = string.Format("Mouse button not supported: '{0}'.", pMouseButton);
                        throw new NotSupportedException(errorMessage);
                    }
            }
        }
        #endregion
        #endregion
    }
}